package main

import (
	"fmt"
	"math"
	"reflect"
)

// 方法

type Point struct{ x, y float64 }

// 传统的函数声明
func Distance(p, q Point) float64 {
	fmt.Println("p的类型:", reflect.TypeOf(p).String()) // p的类型: main.Point
	fmt.Println("3的类型:", reflect.TypeOf(3).String()) // int
	return math.Hypot(q.x-p.x, q.y-p.y)
}

// 方法声明
// 附加的参数p, 叫做方法的接收器(receiver), 早期的面向对象语言留下的遗产将调用一个方法称为“向一个对象发送消息”
// p.MethodDistance的表达式叫做选择器，因为他会选择合适的对应p这个对象的Distance方法来执行
func (p Point) MethodDistance(q Point) float64 {
	return math.Hypot(q.x-p.x, q.y-p.y)
}

// 指针方法
func (p *Point) PointMethodDistance(q Point) float64 {
	return math.Hypot(q.x-p.x, q.y-p.y)
}

func main() {
	// 1. 方法声明
	p := Point{1, 2}
	q := Point{4, 5}
	fmt.Println(Distance(p, q))      // 4.242640687119286
	fmt.Println(p.MethodDistance(q)) // 4.242640687119286

	// 2. 基于指针对象的方法(值拷贝, 省内存)
	fmt.Println((&p).PointMethodDistance(q)) // 4.242640687119286
}
